/*     */ package com.zimbra.cs.dav.resource;
/*     */ 
/*     */ import com.google.common.io.Closeables;
/*     */ import com.zimbra.common.mailbox.ContactConstants;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.HttpUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.dav.DavContext;
/*     */ import com.zimbra.cs.dav.DavElements.CardDav;
/*     */ import com.zimbra.cs.dav.DavException;
/*     */ import com.zimbra.cs.dav.DavException.InvalidData;
/*     */ import com.zimbra.cs.dav.property.CardDavProperty;
/*     */ import com.zimbra.cs.dav.property.ResourceProperty;
/*     */ import com.zimbra.cs.index.ContactHit;
/*     */ import com.zimbra.cs.index.SortBy;
/*     */ import com.zimbra.cs.index.ZimbraHit;
/*     */ import com.zimbra.cs.index.ZimbraQueryResults;
/*     */ import com.zimbra.cs.mailbox.Contact;
/*     */ import com.zimbra.cs.mailbox.ContactGroup;
/*     */ import com.zimbra.cs.mailbox.ContactGroup.Member;
/*     */ import com.zimbra.cs.mailbox.ContactGroup.Member.Type;
/*     */ import com.zimbra.cs.mailbox.Folder;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxIndex;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.service.FileUploadServlet.Upload;
/*     */ import com.zimbra.cs.service.formatter.VCard;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import java.io.ByteArrayInputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.util.ArrayList;
/*     */ import java.util.EnumSet;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import org.dom4j.Element;
/*     */ import org.dom4j.QName;
/*     */ import org.json.JSONException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class AddressObject
/*     */   extends MailItemResource
/*     */ {
/*     */   public static final String VCARD_EXTENSION = ".vcf";
/*     */   private static final String XABSKIND = "X-ADDRESSBOOKSERVER-KIND";
/*     */   private static final String XABSMEMBER = "X-ADDRESSBOOKSERVER-MEMBER";
/*     */   
/*     */   public AddressObject(DavContext ctxt, Contact item)
/*     */     throws ServiceException
/*     */   {
/*  72 */     super(ctxt, item);
/*  73 */     setProperty("getcontenttype", "text/vcard");
/*     */     
/*     */ 
/*     */ 
/*  77 */     setProperty("getcontentlength", Integer.toString(item.getFields().size()));
/*     */   }
/*     */   
/*     */   public boolean isCollection()
/*     */   {
/*  82 */     return false;
/*     */   }
/*     */   
/*     */   public ResourceProperty getProperty(Element prop)
/*     */   {
/*  87 */     if (prop.getQName().equals(DavElements.CardDav.E_ADDRESS_DATA)) {
/*  88 */       return CardDavProperty.getAddressbookData(prop, this);
/*     */     }
/*  90 */     return super.getProperty(prop);
/*     */   }
/*     */   
/*     */   public InputStream getContent(DavContext ctxt) throws DavException, IOException
/*     */   {
/*     */     try {
/*  96 */       return new ByteArrayInputStream(toVCard(ctxt).getBytes("UTF-8"));
/*     */     } catch (ServiceException e) {
/*  98 */       ZimbraLog.dav.warn("can't get content for Contact %d", Integer.valueOf(this.mId), e);
/*     */     }
/* 100 */     return null;
/*     */   }
/*     */   
/*     */   private static void constructContactGroupFromAppleXProps(DavContext ctxt, Account ownerAccount, VCard vcard, Contact existingContact, int folderId) {
/* 104 */     Map<String, String> xprops = Contact.decodeXProps((String)vcard.fields.get("vcardXProps"));
/* 105 */     String kind = (String)xprops.get("X-ADDRESSBOOKSERVER-KIND");
/* 106 */     String memberList = (String)xprops.get("X-ADDRESSBOOKSERVER-MEMBER");
/* 107 */     if ((kind != null) && (kind.compareTo("group") == 0)) {
/*     */       try { ContactGroup contactGroup;
/*     */         ContactGroup contactGroup;
/* 110 */         if (existingContact == null) {
/* 111 */           contactGroup = ContactGroup.init();
/*     */         } else {
/* 113 */           contactGroup = ContactGroup.init(existingContact, true);
/*     */           
/* 115 */           ArrayList<ContactGroup.Member> membersToRemove = new ArrayList();
/* 116 */           for (ContactGroup.Member member : contactGroup.getMembers()) {
/* 117 */             if (ContactGroup.Member.Type.CONTACT_REF.equals(member.getType())) {
/* 118 */               ItemId itemId = new ItemId(member.getValue(), existingContact.getAccount().getId());
/* 119 */               if (itemId.belongsTo(existingContact.getAccount()))
/*     */               {
/* 121 */                 Contact c = getContactByUID(ctxt, itemId.toString(), existingContact.getAccount(), folderId);
/* 122 */                 if (c != null)
/* 123 */                   membersToRemove.add(member);
/*     */               }
/*     */             }
/*     */           }
/* 127 */           for (ContactGroup.Member member : membersToRemove)
/* 128 */             contactGroup.removeMember(member.getType(), member.getValue());
/*     */         }
/* 130 */         if (memberList != null) {
/*     */           try {
/* 132 */             String[] members = Contact.parseMultiValueAttr(memberList);
/* 133 */             for (String uidStr : members) {
/* 134 */               if (uidStr.startsWith("urn:uuid:"))
/* 135 */                 uidStr = uidStr.substring(9);
/* 136 */               Contact c = getContactByUID(ctxt, uidStr, ownerAccount, folderId);
/* 137 */               if (c != null)
/*     */               {
/* 139 */                 ItemId itemId = new ItemId(c);
/* 140 */                 contactGroup.addMember(ContactGroup.Member.Type.CONTACT_REF, itemId.toString());
/*     */               }
/*     */             }
/*     */           } catch (JSONException e) {
/* 144 */             ZimbraLog.dav.debug("can't parse xprop %s", memberList, e);
/*     */           }
/*     */         }
/*     */         
/* 148 */         vcard.fields.put(ContactConstants.A_type, "group");
/* 149 */         vcard.fields.put(ContactConstants.A_groupMember, contactGroup.encode());
/*     */         
/* 151 */         xprops.remove("X-ADDRESSBOOKSERVER-KIND");
/* 152 */         xprops.remove("X-ADDRESSBOOKSERVER-MEMBER");
/* 153 */         vcard.fields.put("vcardXProps", Contact.encodeXProps(xprops));
/*     */       } catch (ServiceException e) {
/* 155 */         ZimbraLog.dav.debug("can't parse xprop %s", memberList, e);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static void populateContactGroupAppleXProps(DavContext ctxt, Contact contact) {
/* 161 */     if (!contact.isContactGroup())
/* 162 */       return;
/* 163 */     ContactGroup contactGroup = null;
/*     */     try {
/* 165 */       contactGroup = ContactGroup.init(contact.get(ContactConstants.A_groupMember));
/*     */     } catch (ServiceException e) {
/* 167 */       ZimbraLog.dav.warn("can't get group members for Contact %d", Integer.valueOf(contact.getId()), e);
/*     */     }
/*     */     
/* 170 */     Map<String, String> xprops = contact.getXProps();
/* 171 */     xprops.put("X-ADDRESSBOOKSERVER-KIND", "group");
/* 172 */     if (contactGroup != null) {
/* 173 */       ArrayList<String> memberList = new ArrayList(contactGroup.getMembers().size());
/*     */       try {
/* 175 */         for (ContactGroup.Member member : contactGroup.getMembers()) {
/* 176 */           if (member.getType().equals(ContactGroup.Member.Type.CONTACT_REF)) {
/* 177 */             ItemId itemId = new ItemId(member.getValue(), contact.getAccount().getId());
/* 178 */             if (itemId.belongsTo(contact.getAccount()))
/*     */             {
/* 180 */               Contact c = getContactByUID(ctxt, itemId.toString(), contact.getAccount(), contact.getFolderId());
/* 181 */               if (c != null)
/* 182 */                 memberList.add("urn:uuid:" + VCard.getUid(c));
/*     */             }
/*     */           }
/*     */         }
/* 186 */         xprops.put("X-ADDRESSBOOKSERVER-MEMBER", Contact.encodeMultiValueAttr((String[])memberList.toArray(new String[0])));
/*     */       } catch (JSONException e) {
/* 188 */         ZimbraLog.dav.warn("can't create group members xprops for Contact %d", Integer.valueOf(contact.getId()), e);
/*     */       } catch (ServiceException e) {
/* 190 */         ZimbraLog.dav.warn("can't create group members xprops for Contact %d", Integer.valueOf(contact.getId()), e);
/*     */       }
/*     */     }
/* 193 */     contact.setXProps(xprops);
/*     */   }
/*     */   
/*     */   public String toVCard(DavContext ctxt) throws ServiceException, DavException {
/* 197 */     Contact contact = (Contact)getMailItem(ctxt);
/* 198 */     populateContactGroupAppleXProps(ctxt, contact);
/* 199 */     return VCard.formatContact(contact, null, true, false).getFormatted();
/*     */   }
/*     */   
/* 202 */   public String toVCard(DavContext ctxt, java.util.Collection<String> attrs) throws ServiceException, DavException { if ((attrs == null) || (attrs.isEmpty()))
/* 203 */       return toVCard(ctxt);
/* 204 */     Contact contact = (Contact)getMailItem(ctxt);
/* 205 */     populateContactGroupAppleXProps(ctxt, contact);
/* 206 */     return VCard.formatContact(contact, attrs, true).getFormatted();
/*     */   }
/*     */   
/*     */   public static DavResource create(DavContext ctxt, String name, Collection where) throws DavException, IOException {
/* 210 */     FileUploadServlet.Upload upload = ctxt.getUpload();
/* 211 */     String buf = new String(ByteUtil.getContent(upload.getInputStream(), (int)upload.getSize()), "utf-8");
/* 212 */     Mailbox mbox = null;
/* 213 */     DavResource res = null;
/*     */     try {
/* 215 */       url = ctxt.getItem();
/* 216 */       if (url.endsWith(".vcf")) {
/* 217 */         url = url.substring(0, url.length() - 4);
/* 218 */         url = HttpUtil.urlUnescape(url);
/*     */       }
/* 220 */       mbox = where.getMailbox(ctxt);
/* 221 */       for (VCard vcard : VCard.parseVCard(buf))
/* 222 */         if (!vcard.fields.isEmpty())
/*     */         {
/* 224 */           vcard.fields.put("vcardURL", url);
/* 225 */           String uid = vcard.uid;
/* 226 */           Account ownerAccount = Provisioning.getInstance().getAccountById(where.mOwnerId);
/* 227 */           Contact c = null;
/*     */           
/* 229 */           if (uid != null) {
/* 230 */             vcard.fields.put("vcardUID", uid);
/* 231 */             res = UrlNamespace.getResourceAt(ctxt, ctxt.getUser(), ctxt.getPath());
/*     */           }
/* 233 */           if (res == null) {
/* 234 */             String ifnonematch = ctxt.getRequest().getHeader("If-None-Match");
/* 235 */             if (ifnonematch == null) {
/* 236 */               throw new DavException("item does not exists", 409);
/*     */             }
/* 238 */             constructContactGroupFromAppleXProps(ctxt, ownerAccount, vcard, null, where.getId());
/* 239 */             c = mbox.createContact(ctxt.getOperationContext(), vcard.asParsedContact(), where.mId, null);
/* 240 */             res = new AddressObject(ctxt, c);
/* 241 */             res.mNewlyCreated = true;
/*     */           } else {
/* 243 */             String etag = ctxt.getRequest().getHeader("If-Match");
/* 244 */             String itemEtag = res.getEtag();
/* 245 */             if ((etag != null) && (!etag.equals(itemEtag)))
/* 246 */               throw new DavException("item etag does not match", 409);
/* 247 */             MailItemResource mir = (MailItemResource)res;
/* 248 */             constructContactGroupFromAppleXProps(ctxt, ownerAccount, vcard, (Contact)mir.getMailItem(ctxt), where.getId());
/* 249 */             vcard.merge((Contact)mir.getMailItem(ctxt));
/* 250 */             mbox.modifyContact(ctxt.getOperationContext(), mir.getId(), vcard.asParsedContact());
/* 251 */             res = UrlNamespace.getResourceAt(ctxt, ctxt.getUser(), ctxt.getPath());
/*     */           }
/*     */         }
/*     */     } catch (ServiceException e) { String url;
/* 255 */       throw new DavException.InvalidData(DavElements.CardDav.E_VALID_ADDRESS_DATA, "cannot parse vcard");
/*     */     }
/* 257 */     if (res == null)
/* 258 */       throw new DavException.InvalidData(DavElements.CardDav.E_VALID_ADDRESS_DATA, "cannot parse vcard");
/* 259 */     return res;
/*     */   }
/*     */   
/*     */   public static AddressObject getAddressObjectByUID(DavContext ctxt, String uid, Account account, Folder f) throws ServiceException {
/* 263 */     Contact c = getContactByUID(ctxt, uid, account, f != null ? f.getId() : -1);
/* 264 */     if (c == null)
/* 265 */       return null;
/* 266 */     return new AddressObject(ctxt, c);
/*     */   }
/*     */   
/*     */   public static AddressObject getAddressObjectByUID(DavContext ctxt, String uid, Account account) throws ServiceException {
/* 270 */     return getAddressObjectByUID(ctxt, uid, account, null);
/*     */   }
/*     */   
/*     */   private static Contact getContactByUID(DavContext ctxt, String uid, Account account, int folderId) throws ServiceException {
/* 274 */     Contact item = null;
/* 275 */     Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(account);
/* 276 */     if (uid.endsWith(".vcf")) {
/* 277 */       uid = uid.substring(0, uid.length() - ".vcf".length());
/*     */       
/* 279 */       uid = HttpUtil.urlUnescape(uid);
/*     */     }
/* 281 */     int id = 0;
/* 282 */     int index = uid.indexOf(':');
/* 283 */     if (index > 0) {
/* 284 */       String accountId = uid.substring(0, index);
/*     */       try {
/* 286 */         if (accountId.equals(account.getId())) {
/* 287 */           id = Integer.parseInt(uid.substring(index + 1));
/*     */         }
/*     */       } catch (NumberFormatException e) {}
/*     */     }
/* 291 */     if (id > 0) {
/* 292 */       item = mbox.getContactById(ctxt.getOperationContext(), Integer.parseInt(uid.substring(index + 1)));
/*     */     } else {
/* 294 */       ZimbraQueryResults zqr = null;
/* 295 */       StringBuilder query = new StringBuilder();
/* 296 */       query.append("#").append("vcardUID").append(":");
/*     */       
/* 298 */       query.append("\"").append(uid.replace("\"", "\\\"")).append("\"");
/* 299 */       query.append(" OR ").append("#").append("vcardURL").append(":");
/* 300 */       query.append("\"").append(uid.replace("\"", "\\\"")).append("\"");
/* 301 */       ZimbraLog.dav.debug("query %s", new Object[] { query.toString() });
/*     */       try {
/* 303 */         zqr = mbox.index.search(ctxt.getOperationContext(), query.toString(), EnumSet.of(MailItem.Type.CONTACT), SortBy.NAME_ASC, 10);
/*     */         
/*     */ 
/* 306 */         while (zqr.hasNext()) {
/* 307 */           ZimbraHit hit = zqr.getNext();
/* 308 */           if ((hit instanceof ContactHit)) {
/* 309 */             item = ((ContactHit)hit).getContact();
/* 310 */             if (folderId < 0)
/*     */               break;
/* 312 */             if (item.getFolderId() == folderId)
/*     */               break;
/* 314 */             item = null;
/*     */           }
/*     */         }
/*     */       } catch (Exception e) {
/* 318 */         ZimbraLog.dav.error("can't search for: uid=%s", uid, e);
/*     */       } finally {
/* 320 */         Closeables.closeQuietly(zqr);
/*     */       }
/*     */     }
/*     */     
/* 324 */     if ((item != null) && (folderId >= 0) && (item.getFolderId() != folderId)) {
/* 325 */       item = null;
/*     */     }
/* 327 */     return item;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/dav/resource/AddressObject.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */